package com.nseeod.gui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Observable;
import java.util.Observer;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.nseeod.constant.AppConstants;
import com.nseeod.download.Download;
import com.toedter.calendar.JDateChooser;

// The Download Manager.
public class DownloadManager extends JFrame
        implements Observer {
    
    /**
	 * 
	 */
	private static final long serialVersionUID = -3132040012603981264L;

	// Add download text field.
    private JDateChooser startDate;
    private JDateChooser endDate;
    // Download table's data model.
    private DownloadsTableModel tableModel;
    
    // Table listing downloads.
    private JTable table;
    
    // These are the buttons for managing the selected download.
    private JButton startButton, pauseButton, resumeButton;
    private JButton cancelButton, clearButton, clearAllButton;
    
    // Currently selected download.
    private Download selectedDownload;
    
    // Flag for whether or not table selection is being cleared.
    private boolean clearing;
    private boolean clearingAll;
    
    // Constructor for Download Manager.
    public DownloadManager() {
        // Set application title.
        setTitle("Download Manager");
        
        // Set window size.
        setSize(640, 480);
        
        // Handle window closing events.
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                actionExit();
            }
        });
        
        // Set up file menu.
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        fileMenu.setMnemonic(KeyEvent.VK_F);
        JMenuItem fileExitMenuItem = new JMenuItem("Exit",
                KeyEvent.VK_X);
        fileExitMenuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                actionExit();
            }
        });
        fileMenu.add(fileExitMenuItem);
        menuBar.add(fileMenu);
        setJMenuBar(menuBar);
        
        // Set up add panel.
        JPanel addPanel = new JPanel();
        JButton addButton = new JButton("Add Download");
        addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                actionAdd();
            }
        });
        
        addPanel.add(addButton);
        
        startDate = new JDateChooser();
        addPanel.add(startDate);
        endDate = new JDateChooser();
        addPanel.add(endDate);
        JButton addAllButton = new JButton("Add All Download");
        addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                actionAddAll();
            }
        });
        addPanel.add(addButton);
        // Set up Downloads table.
        tableModel = new DownloadsTableModel();
        table = new JTable(tableModel);
        table.getSelectionModel().addListSelectionListener(new
                ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                if(!clearingAll)
            	tableSelectionChanged();
            }
        });
        // Allow only one row at a time to be selected.
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        
        // Set up ProgressBar as renderer for progress column.
        ProgressRenderer renderer = new ProgressRenderer(0, 100);
        renderer.setStringPainted(true); // show progress text
        table.setDefaultRenderer(JProgressBar.class, renderer);
        
        // Set table's row height large enough to fit JProgressBar.
        table.setRowHeight(
                (int) renderer.getPreferredSize().getHeight());
        
        // Set up downloads panel.
        JPanel downloadsPanel = new JPanel();
        downloadsPanel.setBorder(
                BorderFactory.createTitledBorder("Downloads"));
        downloadsPanel.setLayout(new BorderLayout());
        downloadsPanel.add(new JScrollPane(table),
                BorderLayout.CENTER);
        
        // Set up buttons panel.
        JPanel buttonsPanel = new JPanel();
        startButton = new JButton("Start");
        startButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                actionStart();
            }
        });
        startButton.setEnabled(true);
        buttonsPanel.add(startButton);
        pauseButton = new JButton("Pause");
        pauseButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                actionPause();
            }
        });
        pauseButton.setEnabled(false);
        buttonsPanel.add(pauseButton);
        resumeButton = new JButton("Resume");
        resumeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                actionResume();
            }
        });
        resumeButton.setEnabled(false);
        buttonsPanel.add(resumeButton);
        cancelButton = new JButton("Cancel");
        cancelButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                actionCancel();
            }
        });
        cancelButton.setEnabled(false);
        buttonsPanel.add(cancelButton);
        clearButton = new JButton("Clear");
        clearButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                actionClear();
            }
        });
        clearButton.setEnabled(false);
        buttonsPanel.add(clearButton);
        
        clearAllButton = new JButton("Clear All");
        clearAllButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                actionClearAll();
            }
        });
        clearAllButton.setEnabled(true);
        buttonsPanel.add(clearAllButton);
        
        // Add panels to display.
        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(addPanel, BorderLayout.NORTH);
        getContentPane().add(downloadsPanel, BorderLayout.CENTER);
        getContentPane().add(buttonsPanel, BorderLayout.SOUTH);
    }
    
    // Exit this program.
    private void actionExit() {
        System.exit(0);
    }
    
    // Add a new download.
    private void actionAdd() {
    	//actionClearAll();
    	Calendar startDate = this.startDate.getCalendar();
		Calendar endDate = this.endDate.getCalendar();
		String nseBhavCopyURL = AppConstants.getNseBhavCopyURL();
		Format nseFormatter = new SimpleDateFormat("ddMMMyyyy");
    	
		String ddmmmyyyy = null;
		String nseURL = null;
		URL url;
		for (; startDate.getTimeInMillis() <= endDate.getTimeInMillis(); startDate
				.add(Calendar.DAY_OF_YEAR, 1)) {
			if (startDate.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY
			&& startDate.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
				ddmmmyyyy = nseFormatter.format(startDate.getTime())
						.toUpperCase();
				nseURL = (new StringBuilder(nseBhavCopyURL)).append(
						ddmmmyyyy.substring(5)).append("/").append(
						ddmmmyyyy.substring(2, 5)).append("/cm").append(
						ddmmmyyyy).append("bhav.csv").toString();
				try {
					tableModel.addDownload(new Download(new URL(nseURL),AppConstants.getDataFolderPath()));
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		}
    	
    }
    // Add a new download.
    private void actionAddAll() {
    	//System.out.println(nseURL);
            //tableModel.addDownload(new Download(verifiedUrl));
            //addTextField.setText(""); // reset add text field
        
    }
    
    // Verify download URL.
    private URL verifyUrl(String url) {
        // Only allow HTTP URLs.
        if (!url.toLowerCase().startsWith("http://"))
            return null;
        
        // Verify format of URL.
        URL verifiedUrl = null;
        try {
            verifiedUrl = new URL(url);
        } catch (Exception e) {
            return null;
        }
        
        // Make sure URL specifies a file.
        if (verifiedUrl.getFile().length() < 2)
            return null;
        
        return verifiedUrl;
    }
    
    // Called when table row selection changes.
    private void tableSelectionChanged() {
    /* Unregister from receiving notifications
       from the last selected download. */
        if (selectedDownload != null)
            selectedDownload.deleteObserver(DownloadManager.this);
        
    /* If not in the middle of clearing a download,
       set the selected download and register to
       receive notifications from it. */
        if (!clearing && table.getSelectedRow() >=0) {
            selectedDownload =
                    tableModel.getDownload(table.getSelectedRow());
            selectedDownload.addObserver(DownloadManager.this);
            updateButtons();
        }
    }
 // Pause the selected download.
    private void actionStart() {
        for(int i = 0 ; i <AppConstants.getNumberOfThread() ; i++)
        {	
        	tableModel.getDownload(i).start();
        	updateButtons();
        }
    }
    // Pause the selected download.
    private void actionPause() {
        selectedDownload.pause();
        updateButtons();
    }
    
    // Resume the selected download.
    private void actionResume() {
        selectedDownload.resume();
        updateButtons();
    }
    
    // Cancel the selected download.
    private void actionCancel() {
        selectedDownload.cancel();
        updateButtons();
    }
    
    // Clear the selected download.
    private void actionClear() {
        clearing = true;
        tableModel.clearDownload(table.getSelectedRow());
        clearing = false;
        selectedDownload = null;
        updateButtons();
    }
 // Clear all download.
    private void actionClearAll() {
    	 if (selectedDownload != null)
             selectedDownload.deleteObserver(DownloadManager.this);
    	selectedDownload = null;
    	clearingAll = true;
        tableModel.clearAllDownload();
        clearingAll = false;
        updateButtons();
    }
    
  /* Update each button's state based off of the
     currently selected download's status. */
    private void updateButtons() {
        if (selectedDownload != null) {
            int status = selectedDownload.getStatus();
            switch (status) {
                case Download.DOWNLOADING:
                	startButton.setEnabled(false);
                    pauseButton.setEnabled(true);
                    resumeButton.setEnabled(false);
                    cancelButton.setEnabled(true);
                    clearButton.setEnabled(false);
                    break;
                case Download.PAUSED:
                	startButton.setEnabled(false);
                    pauseButton.setEnabled(false);
                    resumeButton.setEnabled(true);
                    cancelButton.setEnabled(true);
                    clearButton.setEnabled(false);
                    break;
                case Download.ERROR:
                	startButton.setEnabled(false);
                    pauseButton.setEnabled(false);
                    resumeButton.setEnabled(true);
                    cancelButton.setEnabled(false);
                    clearButton.setEnabled(true);
                    break;
                case Download.READY:
                	startButton.setEnabled(true);
                    pauseButton.setEnabled(false);
                    resumeButton.setEnabled(false);
                    cancelButton.setEnabled(false);
                    clearButton.setEnabled(true);
                    break;
                default: // COMPLETE or CANCELLED
                    pauseButton.setEnabled(false);
                    resumeButton.setEnabled(false);
                    cancelButton.setEnabled(false);
                    clearButton.setEnabled(true);
            }
        } else {
            // No download is selected in table.
            pauseButton.setEnabled(false);
            resumeButton.setEnabled(false);
            cancelButton.setEnabled(false);
            clearButton.setEnabled(false);
        }
    }
    
  /* Update is called when a Download notifies its
     observers of any changes. */
    public void update(Observable o, Object arg) {
        // Update buttons if the selected download has changed.
        if (selectedDownload != null && selectedDownload.equals(o))
            updateButtons();
    }
    
    // Run the Download Manager.
    public static void main(String[] args) {
        DownloadManager manager = new DownloadManager();
        Calendar c = Calendar.getInstance();
        c.set(2007, 8, 26);
        manager.startDate.setCalendar(c);
        c = Calendar.getInstance();
        c.set(2007, 9, 15);
        manager.endDate.setCalendar(c);
        manager.show();
        AppConstants.setDataLocation("D:/StockData/NSE");
		AppConstants.setTempLocation("D:/StockData/NSE");
		File dir = new File(AppConstants.getTempFolderPath());
		if (!(dir.exists() && dir.isDirectory()))
			dir.mkdir();
		dir = new File(AppConstants.getDataFolderPath());
		if (!(dir.exists() && dir.isDirectory()))
			dir.mkdir();
		dir = new File(AppConstants.getNseFolderPath());
		if (!(dir.exists() && dir.isDirectory()))
			dir.mkdir();
		
		//downloadMetaData();
    }
    public static void downloadMetaData()
	{
		try {
			new Download(new URL(AppConstants.getListed()));
			new Download(new URL(AppConstants.getDelisted()));
			new Download(new URL(AppConstants.getNameChange()));
			new Download(new URL(AppConstants.getSuspended()));
			new Download(new URL(AppConstants.getSymbolChange()));
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}